#!/usr/bin/python
# -*- coding: utf-8 -*-

DEFAULT_WAIT = 1 # tempo em segundos de espera entre partidas

import os, time

import pygame
from pygame.locals import *
from pygame.sprite import RenderUpdates
from pygame.time   import Clock


from paddle       import Paddle
from ball         import Ball
from scoredisplay import ScoreDisplay

class Game:
    screen      = None
    run         = True
    img_p1      = None
    img_p2      = None
    img_ball    = None
    img_table   = None
    wait        = DEFAULT_WAIT
    dt          = 16


    
    def __init__( self, size, fullscreen ):
        """
        Esta é a função que inicializa o pygame, define a resolução da tela,
        caption, e disabilitamos o mouse dentro desta.
        """
        pygame.init()
        self.flags = DOUBLEBUF
        if fullscreen:
            self.flags |= FULLSCREEN
        self.screen      = pygame.display.set_mode( size, self.flags )
        self.screen_size = self.screen.get_size()

        pygame.mouse.set_visible( 0 )
        pygame.display.set_caption( 'Ping Pong' )

        self.load_images()
    # init()



    def load_images( self ):
        """
        Lê as imagens necessarias pelo jogo.
        """
        p = "imagens" + os.path.sep
        self.img_p1    = pygame.image.load( p + "p1.png" )
        self.img_p2    = pygame.image.load( p + "p2.png" )
        self.img_ball  = pygame.image.load( p + "ball.png" )
        self.img_table = pygame.image.load( p + "table.png" )
    # load_images()



    def setup( self ):
        """
        Faz a configuração inicial, imprime o fundo e inicia os jogadores.
        """
        # Imprimimos o fundo. Ele não precisa ser um personagem pois ele
        # não atua (muda, move, ...)
        self.screen.blit( self.img_table, ( 0, 0 ) )
        pygame.display.flip()
        
        # Area de movimentacao dentro da mesa (x, y, w, h)
        tma = Rect( 10, 30, 780, 570 )

        # Area de movimentacao de cada jogador:
        p1_ma   = Rect( 0, tma.top, tma.left, tma.height )
        p2_ma   = Rect( tma.left + tma.width, tma.top, tma.left, tma.height )
        ball_ma = Rect( 0, tma.top, tma.width + 2 * tma.left, tma.height  )
        

        
        # Inicia Jogadores: imagem, posicao inicial, area de movimentacao
        s = os.path.join( "sounds", "paddle.wav" )
        self.p1   = Paddle( self.img_p1, p1_ma.topleft, p1_ma, s )
        self.p2   = Paddle( self.img_p2, p2_ma.topleft, p2_ma, s )
        self.ball = Ball( self.img_ball, ball_ma, tma )

        # Centraliza Jogadores:
        self.p1.rect.center = p1_ma.center
        self.p2.rect.center = p2_ma.center        

        # Grupo de elementos atuantes:
        self.group = RenderUpdates( [ self.ball,
                                      self.p1,
                                      self.p2 ] )

        
        # Placar:
        r = Rect( 0, 0, tma.width + 2 * tma.left, tma.top )
        self.score = ScoreDisplay( r )
    # setup()

    
    def handle_events( self ):
        """
        Trata o evento e toma a ação necessária.
        """
        for event in pygame.event.get():
            t = event.type
            if t in ( KEYDOWN, KEYUP ):
                k = event.key
        
            if t == QUIT:
                self.run = False

            elif t == KEYDOWN:
                if   k == K_ESCAPE:
                    self.run = False
                elif k == K_a:
                    self.p1.set_move_up()
                elif k == K_z:
                    self.p1.set_move_down()
                elif k == K_UP:
                    self.p2.set_move_up()
                elif k == K_DOWN:
                    self.p2.set_move_down()
            
            elif t == KEYUP:
                if   k == K_a:
                    self.p1.unset_move_up()
                elif k == K_z:
                    self.p1.unset_move_down()
                elif k == K_UP:
                    self.p2.unset_move_up()
                elif k == K_DOWN:
                    self.p2.unset_move_down()
    # handle_events()



    def manage( self ):
        """
        Verifica se a bola saiu e algum jogador pegou e faça o necessário.

        Aqui é que podemos adicionar mais lógica no jogo.
        """
        out = self.ball.check_out()
        if out:
            if out == -1:
                if self.p1.catch( self.ball ):
                    # P1 pegou, retorne a bola
                    # emite som:
                    self.p1.soundeffect()
                    # inverte trajetória da bola
                    self.ball.invert_speed_x()
                    # Transfere movimento vertical para bola ( 50 % )
                    self.ball.inc_speed_y( self.p1.get_speed()[ 1 ] * 0.5 )
                    return
                else:
                    # Ponto para P2
                    self.score.p2 += 1
                    self.restart()
            
            if out == 1:
                if self.p2.catch( self.ball ):
                    # P2 pegou, retorne a bola
                    # emite som:
                    self.p2.soundeffect()
                    # inverte trajetória da bola
                    self.ball.invert_speed_x()
                    # Transfere movimento vertical para bola ( 50 % )
                    self.ball.inc_speed_y( self.p2.get_speed()[ 1 ] * 0.5 )
                    return
                else:
                    # Ponto para P1
                    self.score.p1 += 1
                    self.restart()
    # manage()



    def restart( self ):
        """Reinicia a jogada."""
        self.ball.start()
        self.wait = DEFAULT_WAIT
    # restart()



    def do_wait( self ):
        """Verifica se deve esperar e configura as ações."""
        if self.wait > 0:
            # decremente o tempo a esperar
            self.wait -= float( self.dt ) / 1000
            # pause a bola
            self.ball.pause = True

            if self.wait <= 0:
                # Já expirou o tempo, volte ao estado normal
                self.wait = 0
                self.ball.pause = False
    # do_wait()

    
    
    def loop( self ):
        """
        Laço principal
        """
        # Faça as configurações iniciais.
        self.setup()
        
        # Inicializamos o relogio e o dt que vai limitar o valor de
        # frames por segundo do jogo
        clock         = Clock()
        interval      = 0

        # assim iniciamos o loop principal do programa
        while self.run:
            clock.tick( 1000 / self.dt )
            interval += 1
            if interval > 1000 and self.dt > 1:
                self.dt -= 1
                interval = 0

            # Trabalha eventos
            self.handle_events()

            # Verifica se deve esperar
            self.do_wait()
            
            # Atualiza posicoes
            self.group.update( self.dt )

            # Faz manutenção do jogo, verifica se alguém perdeu, ...
            self.manage()

            # Limpa posicao atual de elementos, para nao deixar um rastro
            self.group.clear( self.screen, self.img_table )

            # Desenha elementos, guarda areas atualizadas
            r = self.group.draw( self.screen )

            # Atualiza o display com as areas modificadas
            pygame.display.update( r )

            # Mostra Placar e atualiza:
            self.score.draw( self.screen )
            pygame.display.update( self.score )
            
            # ao fim do desenho temos que trocar o front buffer e o back buffer
            # Somente use se usar double buffer!!!
            if self.flags & DOUBLEBUF:
                pygame.display.flip()

            #print "FPS: %0.2f" % clock.get_fps()
        # while self.run
    # loop()
# Game
